package com.omesoft.hksnore.util.snore;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

import com.omesoft.hksnore.util.data.MyDateUtil;
import com.omesoft.hksnore.util.lame.SimpleLame;
import com.omesoft.hksnore.util.photo.SettingUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by Omesoft on 2017/3/5.
 */

public class SnoreRecord {
    private static final String TAG = "SnoreRecord";
    /**
     * 默认采样率<br>
     * 在Android中范围为[4000,48000]<br>
     * 理论上44100Hz是一个通用的值，保证在所有设备上可以工作
     */
    private static final int SAMPLE_RATE_IN_HZ = 32000;
    /**
     * 音频通道设置，CHANNEL_IN_MONO保证所有设备可以使用
     */
    private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
    /**
     * 音频数据格式，为pcm 16bit
     */
    private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    /**
     * 在录制过程中，音频数据写入缓冲区的总数（字节）。 从缓冲区读取的新音频数据总会小于此值。<br>
     * getMinBufferSize(int, int, int)返回AudioRecord 实例创建成功后的最小缓冲区。<br>
     * 设置的值比getMinBufferSize()还小则会导致初始化失败。
     */
    private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, CHANNEL_CONFIG,
            AUDIO_FORMAT);

    private static SnoreRecord RECORDER;


    /**
     * 记录是否正在写入MP3文件
     */
    private boolean isStartWirte = false;

    /**
     * 加载MP3处理类库
     */
    static {
        System.loadLibrary("mp3lame");
    }



    /**
     * 单例模式，获取实例
     *
     * @param
     * @return
     */

    public static SnoreRecord Create() {
        if (RECORDER == null)
            RECORDER = new SnoreRecord();
        return RECORDER;
    }

    /**
     * 获取缓存区大小
     *
     * @return
     */
    public static int GetBufferSize() {
        return BUFFER_SIZE;
    }

    /*----------------------------------------------*/
    private AudioRecord record;
    private byte[] mp3buffer;
    private FileOutputStream output = null;

    private SnoreRecord() {
        record = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_IN_HZ, CHANNEL_CONFIG,
                AUDIO_FORMAT, BUFFER_SIZE);
        if (record == null) {
            Log.e(TAG, "INITIALIZE ERROR");
            throw new ExceptionInInitializerError("INITIALIZE ERROR");
        }
    }

    /**
     * 开始录制
     */
    public void start() {
        if (record != null && record.getState() == AudioRecord.STATE_INITIALIZED) {// 已初始化
            if (record.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) {// 不在录制
                record.startRecording();
            } else
                Log.w(TAG, "alreadly Recording");// 已在录制中
        } else
            Log.e(TAG, "UNINITIALIZE");// 未初始化
    }

    /**
     * 停止录制
     */
    public void stop() {
        if (record != null && record.getState() == AudioRecord.STATE_INITIALIZED) {
            if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {// 在录制中
                record.stop();
                if (isStartWirte) {
                    closeWriteMP3();
                }
            } else
                Log.w(TAG, "alreadly Stop");// 不在录制
        } else
            Log.e(TAG, "UNINITIALIZE");// 未初始化
    }

    /**
     * 从音频硬件录制缓冲区读取数据到buffer。
     *
     * @param buffer
     * @param offset
     * @param size
     * @return 数据长度
     */
    public int read(short[] buffer, int offset, int size) {
        int readSize = 0;
        readSize = record.read(buffer, offset, size);

        if (isStartWirte) {
            if (readSize > 0) {
                int encResult = SimpleLame.encode(buffer, buffer, readSize, mp3buffer);
                Log.e(TAG, "read: encResult     "+encResult );
                if (encResult != 0) {
                    try {
                        output.write(mp3buffer, 0, encResult);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return readSize;
    }

    /**
     * 开始录音 转换为Mp3格式
     *
     * @param buffer
     */
    public void startWirteMP3(short[] buffer,String sleepID) {
        if (!isStartWirte) {
            Log.e("hg", "开始录音>>>>");

            mp3buffer = new byte[(int) (7200 + buffer.length * 2 * 1.25)];
            try {

                File file = new File(SettingUtil.TEXT_RECORD_DIR+"/"+sleepID);
                if (!file.exists()){
                    file.mkdirs();

                }
                String time = MyDateUtil.getSnoreStartTime();
                String filenameTemp = file.toString()+"/"+time + ".mp3";
                Log.e(TAG, "startWirteMP3: "+filenameTemp );


                output = new FileOutputStream(new File(filenameTemp));


            } catch (Exception e) {

                e.printStackTrace();
            }

            SimpleLame.init1(SAMPLE_RATE_IN_HZ, 1, SAMPLE_RATE_IN_HZ, 32);

            isStartWirte = true;
        }

    }

    /**
     * 停止 转换MP3
     */
    public void closeWriteMP3() {
        if (isStartWirte) {
            Log.e("hg", "停止录音>>>>");
            isStartWirte = false;

            int flushResult = SimpleLame.flush(mp3buffer);
            if (flushResult != 0) {
                try {
                    output.write(mp3buffer, 0, flushResult);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            try {
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            SimpleLame.close();
        }

    }

    /**
     * 释放资源
     */
    private void release() {
        stop();
        record.release();
        record = null;
    }

    public void clean() {
        try {
            release();
            RECORDER = null;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
